package org.elip.stewiemaze.server;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.mail.MessagingException;

import org.elip.stewiemaze.server.jdo.PMF;
import org.elip.stewiemaze.server.utils.MailUtils;
import org.elip.stewiemaze.shared.entities.Player;

public class DatastoreHelper {
	
	private static Logger logger = Logger.getLogger(DatastoreHelper.class.getName());
	
	public static void persist(Object object) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		pm.makePersistent(object);
		pm.close();
	}
	
	public static Player verifyUsernameAndPassword(String nickname, String password) {
		nickname = removeSpaces(nickname);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery("SELECT FROM " + Player.class.getName() + " WHERE nickname == " + nickname);
		@SuppressWarnings("unchecked")
		List<Player> attachedPlayers = (List<Player>)query.execute();
		List<Player> players = detachList(pm, attachedPlayers);
		for (Player p : players) {
			if ((p != null) && (p.getPassword() != null) && p.getPassword().equals(password)) return p;
		}
		pm.close();
		return null;
	}
	
	public static Player getPlayer(String nickname) {
		nickname = removeSpaces(nickname);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Player player = pm.getObjectById(Player.class, nickname);
			return player;
		}
		catch (JDOObjectNotFoundException e) {
			return null;
		}
		finally {
			pm.close();
		}
	}
	
	public static void deletePlayer(String userId) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Query query = pm.newQuery("SELECT FROM " + Player.class.getName());
			List<Player> attached = (List<Player>)query.execute();
			if (attached != null) {
				for (Player player : attached) {
					if (player.getUserId().equals(userId)) pm.deletePersistent(player);
				}
			}
		}
		catch (JDOObjectNotFoundException e) {
		}
		finally {
			pm.close();
		}
	}
	
	public static void validatePlayer(String nickname) {
		nickname = removeSpaces(nickname);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Player player = getPlayer(nickname);
		player.setActivated("true");
		pm.makePersistent(player);
		pm.close();
	}
	
	@SuppressWarnings("unchecked")
	public static String[] updateScore(String nickname, Long newScore) {
		nickname = removeSpaces(nickname);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery("SELECT FROM " + Player.class.getName());
		List<Player> players = (List<Player>)query.execute();
		for (Player player : players) {
			if (player.getNickname().equals(nickname) && player.getHighscore() < newScore) {
				player.setHighscore(newScore);
				pm.makePersistent(player);
				if (player.getFacebookUser().equals("true")) {
					try {
						logger.fine("posting score " + player.getHighscore() + " for " + player.getNickname());
						FacebookHelper.postScoreToWall(nickname, player.getHighscore() + "");
						logger.fine("publishing score " + player.getHighscore() + " for " + player.getNickname());
						FacebookHelper.publishScore(player.getHighscore() + "", player.getUserId());
					}
					catch (RuntimeException e) {
						logger.fine("Caught runtime exception " + e.getMessage());
					}
				}
			}
			if (!player.getNickname().equals(nickname)) {
				if ((player.getHighscore() > newScore) && (player.getActivated() != null) && (player.getActivated().equals("true"))) {
					try {
						MailUtils.sendNotification(player.getEmail(), nickname, newScore);
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					} catch (MessagingException e) {
						e.printStackTrace();
					}
				}
			}
		}
		pm.close();
		return getScores();
	}
	
	@SuppressWarnings("unchecked")
	public static void updateAccessToken(String nickname, String accessToken) {
		nickname = DatastoreHelper.removeSpaces(nickname);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery("SELECT FROM " + Player.class.getName());
		List<Player> players = (List<Player>)query.execute();
		for (Player player : players) {
			if (player.getNickname().equals(nickname)) {
				player.setAccessToken(accessToken);
				pm.makePersistent(player);
			}
		}
		pm.close();
		return;
	}

	public static String[] getScores() {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery("SELECT FROM " + Player.class.getName() + " ORDER BY highscore DESC");
		@SuppressWarnings("unchecked")
		List<Player> attachedPlayers = (List<Player>)query.execute();
		List<Player> players = detachList(pm, attachedPlayers);
		if (players != null) {	
			String[] result = new String[players.size()];
			for (int i = 0 ; i < result.length ; i++) {
				Player player = players.get(i);
				if (player.getFacebookUser() != null && player.getFacebookUser().equals("true")) {
					String facebookPhotoElement = "<a href='http://facebook.com/" + player.getUserId() + "' target='_blank'><img src='http://graph.facebook.com/" + player.getUserId() + "/picture'" + "height='50' width='50'/></a>";
					result[i] = (i+1) + ") " + player.getNickname() + " : " + player.getHighscore() + "<br>" + facebookPhotoElement;
				}
				else {
					result[i] = (i+1) + ") " + player.getNickname() + " : " + player.getHighscore();
				}
			}
			pm.close();
			return result;
		}
		pm.close();
		return null;
	}

	public static Player verifyUsername(String name) {
		
		name = removeSpaces(name);
		Logger logger = Logger.getLogger(DatastoreHelper.class.getName());
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery("SELECT FROM " + Player.class.getName() + " WHERE nickname == " + name);
		
		logger.fine("executing query :" + query.toString());
		
		@SuppressWarnings("unchecked")
		List<Player> attachedPlayers = (List<Player>)query.execute();
		
		if (attachedPlayers == null) {
			logger.fine("query returned null!");
			return null;
		}
		
		List<Player> players = detachList(pm, attachedPlayers);
		if (players.size() != 1) return null;
		pm.close();
		return players.get(0);
	}
	
	private static List<Player> detachList(PersistenceManager pm, List<Player> attached) {
		List<Player> detachedList = new ArrayList<Player>();
		if (attached == null) return null;
		for (Player obj : attached) {
			detachedList.add(pm.detachCopy(obj));
		}
		return detachedList;
	}
	
	private static String removeSpaces(String s) {
		String[] elements = s.split(" ");
		if (elements.length == 1) return s;
		String result = "";
		for (String st : elements) {
			result += st;
		}
		return result;
	}

}
